package org.xtext.runtime.interpreter;

import java.util.Set;

import org.xtext.runtime.term.ITerm;
import org.xtext.runtime.term.Term;
import org.xtext.runtime.term.Variable;
import org.xtext.runtime.type.ObjectType;
import org.xtext.runtime.type.Type;
import org.xtext.runtime.type.TypeException;

public class AbstractBuilder {
	protected Set<Variable> variables;
	
	public AbstractBuilder(Set<Variable> variables) {
		this.variables = variables;
	}
	
	public void addBinding(String variable, int value) throws TypeException {
		bind(variable, Term.newInstance(Type.integerType, value));
	}

	public void addBinding(String variable, long value) throws TypeException {
		bind(variable, Term.newInstance(Type.longType, value));
	}
	
	public void addBinding(String variable, float value) throws TypeException {
		bind(variable, Term.newInstance(Type.floatType, value));
	}

	public void addBinding(String variable, double value) throws TypeException {
		bind(variable, Term.newInstance(Type.doubleType, value));
	}
	
	public void addBinding(String variable, String value) throws TypeException {
		bind(variable, Term.newInstance(Type.stringType, value));
	}
	
	public void addBinding(String variable, boolean value) throws TypeException {
		bind(variable, Term.newInstance(Type.booleanType, value));
	}
	
	public void addBinding(String variable, char value) throws TypeException {
		bind(variable, Term.newInstance(Type.characterType, value));
	}
		
	public void addBinding(String variable, Object value) throws TypeException {
		bind(variable, Term.newInstance(new ObjectType(value.getClass()), value));
	}
	
	public void addBinding(String variable, String[] value) {
//		List<ITerm> list = new LinkedList<ITerm>();
//		for (String val: value) {
//			list.add(new StringTerm(val));
//		}
//		
//		bind(variable, new ListTerm("string", list));
	}
	
	public void addBinding(String variable, int[] value) {
//		List<ITerm> list = new LinkedList<ITerm>();
//		for (int val: value) {
//			list.add(new IntegerTerm(val));
//		}
//		
//		bind(variable, new ListTerm("int", list));
	}

	public void addBinding(String variable, long[] value) {
//		List<ITerm> list = new LinkedList<ITerm>();
//		for (long val: value) {
//			list.add(new LongTerm(val));
//		}
//		
//		bind(variable, new ListTerm("long", list));
	}

	private void bind(String variable, ITerm term) throws TypeException {
		for (Variable var : variables) {
			if (var.identifier().equals(variable)) {
				var.assign(term);
				variables.remove(var);
				return;
			}
		}
		
		throw new NoSuchVariableException("no such variable: " + variable);
	}

	public void addBinding(Variable variable, ITerm term) {
		throw new UnsupportedOperationException();
//		retur
//		for (Variable var : variables) {
//			if (var.equals(variable)) {
//				bindings.addBinding(var, term);
//				variables.remove(var);
//				return;
//			}
//		}
//		
//		throw new NoSuchVariableException("no such variable: " + variable);
	}
}
